
package com.eworking.eim.message;

import java.util.Hashtable;

import com.eworking.eim.EIMSessionManager;
import com.eworking.eim.exception.EIMException;
import com.eworking.eim.message.body.MessageBody;
import com.eworking.eim.user.EIMUser;
import com.eworking.eim.user.EIMUserManager;
import com.eworking.eim.util.EIMLog;

import android.os.Parcel;
import android.os.Parcelable;

public class EIMMessage implements Parcelable, Cloneable {
    
    /** 日志输出标记 */
    private static final String _TAG = EIMMessage.class.getSimpleName();
    
    /** 消息类型 */
    public Type type;
    
    /** 消息流向 */
    public Direct direct;
    
    /** 消息状态 */
    public Status status = Status.CREATE;
    
    /** 消息发送人 */
    public EIMUser from;
    
    /** 消息接收人 */
    public EIMUser to;
    
    /** 消息ID */
    public String msgId;
    
    /** 聊天室类型 */
    public ChatType chatType = ChatType.Chat;
    
    /**  */
    public transient int progress = 0;
    
    /** 消息是否确认 */
    public boolean isAcked = false;
    
    /** 消息状态 */
    public Hashtable<String, Object> attributes = null;
    
    /** 消息是否已读 未读：true 已读：false */
    public transient boolean unread = true;
    
    /** 消息是否加密 */
    public static final String _ATTR_ENCRYPTED = "isencrypted";
    
    /** 消息时间 */
    public long msgTime = 0;
    
    /** 消息内容 */
    public MessageBody messageBody = null;
    
    public EIMMessage(Type type) {
        this.type = type;
        this.msgTime = System.currentTimeMillis();
    }
    
    public EIMMessage(Parcel parcel) {
        this.type = Type.valueOf(parcel.readString());
        this.direct = Direct.valueOf(parcel.readString());
        this.msgId = parcel.readString();
        this.msgTime = parcel.readLong();
        this.attributes = new Hashtable<String, Object>();
        parcel.readMap(this.attributes, null);
        this.from = parcel.readParcelable(EIMMessage.class.getClassLoader());
        this.to = parcel.readParcelable(EIMMessage.class.getClassLoader());
        this.messageBody = parcel.readParcelable(EIMMessage.class.getClassLoader());
    }
    
    /**
     * 创建发送消息
     * 
     * @param type 消息类型
     * @return
     */
    public static EIMMessage createSendMessage(Type type) {
        EIMMessage message = new EIMMessage(type);
        message.direct = Direct.SEND;
        message.from = EIMSessionManager.getInstance(null).getCurrentUser();
        return message;
    }
    
    /**
     * 创建接收消息
     * 
     * @param type 消息类型
     * @return
     */
    public static EIMMessage createReceiveMessage(Type type) {
        EIMMessage message = new EIMMessage(type);
        message.direct = Direct.RECEIVE;
        message.to = EIMSessionManager.getInstance(null).getCurrentUser();
        return message;
    }
    
    public Type getType() {
        return type;
    }
    
    public String getFrom() {
        return this.from.getAccount();
    }
    
    public void setFrom(String account) {
        EIMUser user = new EIMUser(account);
        this.from = user;
    }
    
    public String getTo() {
        return this.to.getAccount();
    }
    
    public void setTo(String account) {
        EIMUser user = new EIMUser(account);
        this.to = user;
    }
    
    public MessageBody getMessageBody() {
        return messageBody;
    }
    
    public void setMessageBody(MessageBody messageBody) {
        this.messageBody = messageBody;
    }
    
    public long getMsgTime() {
        return msgTime;
    }
    
    public void setMsgTime(long msgTime) {
        this.msgTime = msgTime;
    }
    
    public String getMsgId() {
        return msgId;
    }
    
    public void setMsgId(String msgId) {
        this.msgId = msgId;
    }
    
    public ChatType getChatType() {
        return chatType;
    }
    
    public void setChatType(ChatType chatType) {
        this.chatType = chatType;
    }
    
    public Direct getDirect() {
        return direct;
    }
    
    public void setDirect(Direct direct) {
        this.direct = direct;
    }
    
    public Status getStatus() {
        return status;
    }
    
    public void setStatus(Status status) {
        this.status = status;
    }
    
    public boolean isAcked() {
        return isAcked;
    }
    
    public void setAcked(boolean isAcked) {
        this.isAcked = isAcked;
    }
    
    public Hashtable<String, Object> getAttributes() {
        return attributes;
    }
    
    public void setAttributes(Hashtable<String, Object> attributes) {
        this.attributes = attributes;
    }
    
    public boolean isUnread() {
        return unread;
    }
    
    public void setUnread(boolean unread) {
        this.unread = unread;
    }
    
    public void setType(Type type) {
        this.type = type;
    }
    
    /**
     * 设置接收人
     * 
     * @param account
     */
    public void setReceipt(String account) {
        EIMUserManager userManager = EIMUserManager.getInstance();
        EIMUser user = null;
        if (account.contains("@")) {
            EIMLog.e(_TAG, "error wrong uesrname format:" + account);
        } else {
            user = userManager.getUserByAccount(account);
        }
        if (user == null) {
            user = new EIMUser(account);
            userManager.addUserInternal(user);
        }
        this.to = user;
    }
    
    public void setAttribute(String key, boolean value) {
        if (this.attributes == null) {
            this.attributes = new Hashtable<String, Object>();
        }
        this.attributes.put(key, value);
    }
    
    public void setAttribute(String key, int value) {
        if (this.attributes == null) {
            this.attributes = new Hashtable<String, Object>();
        }
        this.attributes.put(key, value);
    }
    
    public void setAttribute(String key, String value) {
        if (this.attributes == null) {
            this.attributes = new Hashtable<String, Object>();
        }
        this.attributes.put(key, value);
    }
    
    public boolean getBooleanAttribute(String key) throws EIMException {
        Boolean value = null;
        if (this.attributes != null) {
            value = (Boolean) this.attributes.get(key);
        }
        if (value == null) {
            throw new EIMException("attribute " + key + " not found");
        }
        return value.booleanValue();
    }
    
    public boolean getBooleanAttribute(String key, boolean defalutValue) {
        if (this.attributes == null) {
            return defalutValue;
        }
        Boolean value = (Boolean) this.attributes.get(key);
        if (value == null) {
            return defalutValue;
        }
        return value.booleanValue();
    }
    
    public int getIntAttribute(String key, int defaultValue) {
        Integer value = null;
        if (this.attributes != null) {
            value = (Integer) this.attributes.get(key);
        }
        if (value == null) {
            return defaultValue;
        }
        return value.intValue();
    }
    
    public int getIntAttribute(String key) throws EIMException {
        Integer value = null;
        if (this.attributes != null) {
            value = (Integer) this.attributes.get(key);
        }
        if (value == null) {
            throw new EIMException("attribute " + key + " not found");
        }
        return value.intValue();
    }
    
    public String getStringAttribute(String key) throws EIMException {
        String value = null;
        if (this.attributes != null) {
            value = (String) this.attributes.get(key);
        }
        if (value == null) {
            throw new EIMException("attribute " + key + " not found");
        }
        return value;
    }
    
    public String getStringAttribute(String key, String defaultValue) {
        String value = null;
        if (this.attributes != null) {
            value = String.valueOf(this.attributes.get(key));
        }
        if (value == null) {
            return defaultValue;
        }
        return value;
    }
    
    public static final Parcelable.Creator<EIMMessage> CREATOR = new Parcelable.Creator<EIMMessage>() {
        
        @Override
        public EIMMessage createFromParcel(Parcel parcel) {
            return new EIMMessage(parcel);
        }
        
        @Override
        public EIMMessage[] newArray(int size) {
            return new EIMMessage[size];
        }
    };
    
    @Override
    public int describeContents() {
        return 0;
    }
    
    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeString(this.type.name());
        parcel.writeString(this.direct.name());
        parcel.writeString(this.msgId);
        parcel.writeLong(this.msgTime);
        parcel.writeMap(this.attributes);
        parcel.writeParcelable(this.from, flags);
        parcel.writeParcelable(this.to, flags);
        parcel.writeParcelable(this.messageBody, flags);
    }
    
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
    /**
     * 聊天室类型
     * 
     * @author yangsong
     * @since 1.0
     * @version 2014年7月13日
     */
    public static enum ChatType {
        Chat, GroupChat;
    }
    
    /***
     * 消息流向 - 发送or接收
     * 
     * @author yangsong
     * @since 1.0
     * @version 2014年7月13日
     */
    public static enum Direct {
        SEND, RECEIVE;
    }
    
    /**
     * 消息状态
     * 
     * @author yangsong
     * @since 1.0
     * @version 2014年7月13日
     */
    public static enum Status {
        SUCCESS, FAIL, INPROGRESS, CREATE;
    }
    
    /**
     * 消息类型
     * 
     * @author yangsong
     * @since 1.0
     * @version 2014年7月13日
     */
    public static enum Type {
        TXT, IMAGE, VIDEO, LOCATION, VOICE, FILE, CMD;
    }
}
